using System.Collections.Generic;
using Habanero.Base;
using Habanero.BO;

namespace FireStarterModeller.BO
{
    public class OrderedCollectionController<TBusinessObject>
        where TBusinessObject : class, IOrderableObject, IBusinessObject, new()
    {
        public BusinessObjectCollection<TBusinessObject> Collection { get; private set; }

        public OrderedCollectionController(BusinessObjectCollection<TBusinessObject> collection)
        {
            Collection = collection;
            Collection.BusinessObjectAdded += Collection_OnBusinessObjectAdded;
        }

        private void Collection_OnBusinessObjectAdded(object sender, BOEventArgs<TBusinessObject> e)
        {
            TBusinessObject newBusinessObject = e.BusinessObject;
            if (newBusinessObject.Status.IsNew)
            {
                if (!newBusinessObject.OrdinalPosition.HasValue)
                {
                    newBusinessObject.OrdinalPosition = GetNextOrdinalPosition();
                }
            }
        }

        public int GetNextOrdinalPosition()
        {
            int maxUIOrder = 0;
            maxUIOrder = GetMaxUIOrder(Collection.GetList(), maxUIOrder);
            maxUIOrder = GetMaxUIOrder(Collection.RemovedBusinessObjects, maxUIOrder);
            maxUIOrder = GetMaxUIOrder(Collection.MarkedForDeleteBusinessObjects, maxUIOrder);
            return maxUIOrder + 1;
        }

        private static int GetMaxUIOrder(IEnumerable<TBusinessObject> list, int currentMax)
        {
            foreach (TBusinessObject businessObject in list)
            {
                if (currentMax < businessObject.OrdinalPosition)
                {
                    currentMax = businessObject.OrdinalPosition.GetValueOrDefault(0);
                }
            }
            return currentMax;
        }

        public bool MoveUp(TBusinessObject businessObject)
        {
            Move(businessObject, true);
            return true;
        }

        private void Move(TBusinessObject businessObject, bool moveUp)
        {
            if (businessObject == null) return;
            bool ascending = moveUp;
            List<TBusinessObject> sortedList = Collection.GetList();
            sortedList.Sort((x,y) => Comparer<int?>.Default.Compare(x.OrdinalPosition, y.OrdinalPosition));
            //if (!moveUp) sortedList.Reverse();
            SwapObjectWithPrevious(sortedList, businessObject);
        }

        private static void SwapOrder(TBusinessObject item1, TBusinessObject item2)
        {
            int? tempUIOrder = item1.OrdinalPosition;
            item1.OrdinalPosition = item2.OrdinalPosition;
            item2.OrdinalPosition = tempUIOrder;
        }

        private static void SwapObjectWithPrevious(IList<TBusinessObject> sortedItems, TBusinessObject item)
        {
            TBusinessObject previousItem = null;
            foreach (TBusinessObject currentItem in sortedItems)
            {
                if (currentItem == item) break;
                previousItem = currentItem;
            }
            if (previousItem == null) return;

            SwapOrder(item, previousItem);
        }
    }
}